// Matrices.h: interface for various special matrix classes.
// Part of KenTools library.
// Written by Kwan-Yee Kenneth Wong 2000.
//
//////////////////////////////////////////////////////////////////////
#pragma once


#include "Matrix.h"

//////////////////////////////////////////////////////////////////////
// class CMatrixB for B-Spline
//////////////////////////////////////////////////////////////////////
class CMatrixB : public CMatrix<double>  
{
public:
	// constructors
	CMatrixB();

	// destructors
	virtual ~CMatrixB();

	// retrievers
	virtual bool isValid() const {return(m_nRows==4 && m_nCols==4);}
};

//////////////////////////////////////////////////////////////////////
// class CMatrixB_ for B-Spline
//////////////////////////////////////////////////////////////////////
class CMatrixB_ : public CMatrix<double>  
{
public:
	// constructors
	CMatrixB_();

	// destructors
	virtual ~CMatrixB_();

	// retrievers
	virtual bool isValid() const {return(m_nRows==3 && m_nCols==4);}

};


typedef CMatrix<double> CVector;


///////////////////////////
// class CVector
///////////////////////////
//class CVector : public CMatrix<double>
//{
//public:
//	// constructor
//	CVector(int nDim = 2);
//	CVector(CVector& vec);
//
//	// destructor
//	virtual ~CVector();
//	
//	// retrievers
//	virtual CVector Homogeneous(double fLastDim = 1.0);
//	inline virtual int Size() const {return Rows();}
//	inline virtual bool isValid() const {return(m_nCols==1);}
//
//	// operators
//	virtual const CVector& operator  = (const CVector& vec);
//};


//////////////////////////////////////////////////////////////////////
// class CMatrixP for Camera Projection Matrix
//////////////////////////////////////////////////////////////////////
class CMatrixP : public CMatrix<double>  
{
public:
	// constructors
	CMatrixP();
	CMatrixP(const CMatrixP& P);
	CMatrixP(const CMatrix<double>& P);

	// destructors
	virtual ~CMatrixP();

	// retrievers
	virtual bool isValid() const {return(m_nRows==3 && m_nCols==4);}
		// retrieve the unit viewing direction
		// (i.e. +ve z-direction in camera-coordinates)
	virtual bool GetViewDir(double& x, double& y, double& z) const;
	virtual bool GetViewDir(double V[3]) const;
	virtual CMatrix<double> GetViewDir() const;
		// retrieve the camera center
	virtual bool GetCamCen(double& x, double& y, double& z) const;
	virtual bool GetCamCen(double C[3]) const;
	virtual CMatrix<double> GetCamCen() const;

	// mainpulator
		// estimate the camera given the 3D points X (3xN) and their projections x (2xN)
	virtual bool Calibrate(const CMatrix<double>& X, const CMatrix<double>& x);
		// set the projection matrix as K[R t], P stays unchanged on error
	virtual bool SetKRt(const CMatrix<double>& K, const CMatrix<double>& R, const CMatrix<double>& t);
		// decompose into K[R T]
	virtual bool Decompose(CMatrix<double>& K, CMatrix<double>& R, CMatrix<double>& T) const;
		// form fundamental matrix
	virtual bool FormF(const CMatrixP& P, CMatrix<double>& F) const;
		// project 3D point onto image plane
	virtual bool Project(const double X, const double Y, const double Z, double& u, double& v) const;
	//virtual bool Project(const double X[3], double w[2]) const; // DN: not implemented?
		// triangulation with non-homogeneous coordinates
	virtual CMatrix<double> Triangulate(const CMatrixP& P_, const CMatrix<double>& x, const CMatrix<double> x_) const;
	virtual bool Triangulate(const CMatrixP& P_, const CMatrix<double>& x, const CMatrix<double> x_, CMatrix<double>& X) const;
	virtual bool Triangulate(const CMatrixP& P_, const double x[2], const double x_[2], double X[3]) const;
		// back-projection of points to rays
	virtual bool BackProjection(const double x[2],CMatrix<double>& X) const;
	

};

//////////////////////////////////////////////////////////////////////
// class CMatrixR for rotation matrix
//////////////////////////////////////////////////////////////////////
class CMatrixR : public CMatrix<double>  
{
public:
	// constructors
	CMatrixR();
	CMatrixR(const CMatrixR& R);
	CMatrixR(const CMatrix<double>& R);
    CMatrixR(const double& Theta, const double N[3]);

	// destructors
	virtual ~CMatrixR();

	// initializations
	virtual bool isValid() const; 
		// form the rotation matrix from an axis N (unit vector)
		// and an angle Theta (radian) obeying the right-hand rule
	virtual CMatrixR& SetRot(double Theta, const CMatrix<double>& N);
	virtual CMatrixR& SetRot(double Theta, const double N[3]);
		// form the rotation matrix with rotation angle Theta (radian),
		// and rotation axis defined by the following 2 angles (radians):
		// azimuth Az (ccw in xy-plane) and elevation El (from xy-plane)
	virtual CMatrixR& SetRot(double Theta, double Az, double El);

	// retrievers
		// decompose to retrieve the angle (radian) and axis of rotation
	virtual bool Decompose(double& Theta, CMatrix<double>& N) const;
	virtual bool Decompose(double& Theta, double N[3]) const;
		// retrieve the angle of rotation Theta (radian), 
		// and the azimuth Az (radian) and elevation EL (radian)
		// that define the axis of rotation
	virtual bool Decompose(double& Theta, double& Az, double& El) const;

	// manipulator
	virtual CMatrixR InverseR() const;
};

//////////////////////////////////////////////////////////////////////
// class CMatrixE for essential matrix
//////////////////////////////////////////////////////////////////////
class CMatrixE : public CMatrix<double>
{
public:
	// constructors
	CMatrixE();
	CMatrixE(const CMatrixE& E);
	CMatrixE(const CMatrix<double>& E);

	// destructors
	virtual ~CMatrixE();

	// retrievers
	virtual bool isValid() const {return(m_nRows==3 && m_nCols==3);}
	virtual bool Decompose(CMatrix<double>& R, CMatrix<double>& t, bool bPos=true, int nIdx=2) const;
	virtual bool Decompose2(CMatrix<double>& R1, CMatrix<double>& R2, CMatrix<double>& t, bool bPos=true, int nIdx=2) const;
};